#pragma once

#include "../Common/Net.hpp"
#include "../Common/Dispatcher.hpp"
#include "../Common/Message.hpp"

namespace zgwrpc
{

    namespace server
    {
        // 定义枚举参数字段
        enum class VType
        {
            BOOL = 0,
            INTEGRAL,
            NUMERIC,
            STRING,
            ARRAY,
            OBJECT
        };

        // 服务的描述
        class ServerDescribe
        {
        public:
            using ptr = std::shared_ptr<ServerDescribe>;
            using ServiceCallback = std::function<bool(const Json::Value &, Json::Value &)>; // 一个输入，一个输出
            using ParamsDescribe = std::pair<std::string, VType>;

            ServerDescribe( std::string &&method_name,  ServiceCallback &&callback,  std::vector<ParamsDescribe> &&params_describe, VType return_type)
                : _method_name(move(method_name)), _callback(move(callback)), _params_describe(move(params_describe)), _return_type(return_type)
            {
            }

            std::string MethodName()
            {
                return _method_name;
            }

            bool Call(const Json::Value &params, Json::Value &result)
            {
                return _callback(params, result);
            }
            // 针对收到的参数进行校验
            bool ParamCheck(const Json::Value &params)
            {
                for (auto &desc : _params_describe)
                {
                    if (params.isMember(desc.first) == false)
                    {
                        LOG(LogLevel::ERROR) << "参数字段校验缺失";
                        return false;
                    }
                    if (Check(desc.second, params[desc.first])==false)
                    {
                        LOG(LogLevel::ERROR) << "参数字段校验失败";
                        return false;
                    }
                }
                return true;
            }

        private:
            bool Check(VType type, const Json::Value &value)
            {
                switch (type)
                {
                case VType::BOOL:
                    return value.isBool();
                case VType::INTEGRAL:
                    return value.isIntegral();
                case VType::NUMERIC:
                    return value.isNumeric();
                case VType::STRING:
                    return value.isString();
                case VType::ARRAY:
                    return value.isArray();
                case VType::OBJECT:
                    return value.isObject();
                }
                return false;
            }

        private:
            std::string _method_name;                     // 方法名称
            ServiceCallback _callback;                    // 回调函数
            std::vector<ParamsDescribe> _params_describe; // 参数描述
            VType _return_type;                           // 返回值类型
        };

        // 服务描述构建器
        class ServerDescribeBuilder
        {
        public:
            ServerDescribe::ptr Build()
            {
                return std::make_shared<ServerDescribe>(std::move(_method_name), std::move(_callback), std::move(_params_describe), _value_type);
            }
            void SetMthodName(const std::string &method_name)
            {
                _method_name = method_name;
            }
            void SetCallback(ServerDescribe::ServiceCallback callback)
            {
                _callback = callback;
            }
            void SetParamsDescribe(const std::string &name, VType type)
            {
                _params_describe.push_back(std::make_pair(name, type));
            }
            void SetReturnType(VType return_type)
            {
                _value_type = return_type;
            }

        private:
            std::string _method_name;                                     // 方法名称
            ServerDescribe::ServiceCallback _callback;                    // 回调函数
            std::vector<ServerDescribe::ParamsDescribe> _params_describe; // 参数描述
            VType _value_type;                                            // 返回值类型
        };

        // 管理服务描述
        class ServerManager
        {
        public:
            using ptr = std::shared_ptr<ServerManager>;
            void Insert(const ServerDescribe::ptr &server_desc)
            {
                std::unique_lock<std::mutex> lock(_mutex);
                _server_map.insert(std::make_pair(server_desc->MethodName(), server_desc));
            }
            ServerDescribe::ptr Select(const string &method_name)
            {
                std::unique_lock<std::mutex> lock(_mutex);
                auto it = _server_map.find(method_name);
                if (it != _server_map.end())
                {
                    return it->second;
                }
                return nullptr;
            }
            void Remove(const string &method_name)
            {
                lock_guard<mutex> lock(_mutex);
                _server_map.erase(method_name);
            }

        private:
            std::mutex _mutex;
            std::unordered_map<std::string, ServerDescribe::ptr> _server_map; //根据方法查找对应的服务描述
        };

        // rpc请求处理回调接口,里边只处理rpc请求
        class Rpc_Router
        {
        public:
            using ptr = std::shared_ptr<Rpc_Router>;
            Rpc_Router() : _server_manager(make_shared<ServerManager>())
            {}
            // 针对RPC请求回调的业务函数
            void OnRpcRequest(const BaseConnection::ptr &conn, const RpcRequest::ptr &msg)
            {
                Json::Value result;
                // 1.查询服务描述--判断当前服务是否能被调用
                auto server = _server_manager->Select(msg->method());
                if (server == nullptr)
                {
                    LOG(LogLevel::ERROR) << "服务不存在";   
                    result[KEY_RESULT] = "服务不存在";
                    return RpcResponse(conn, msg, result, RCode::RCODE_NOT_FOUND_SERVICE);
                }

                // 2.进行参数校验，确定是否参数足够
                if (server->ParamCheck(msg->params()) == false)
                {
                    LOG(LogLevel::ERROR) << "参数校验失败";

                    result[KEY_RESULT] = "参数校验失败";
                    return RpcResponse(conn, msg, result, RCode::RCODE_INVALID_PARAMS);
                }

                // 3.调用回调函数，返回结果
                bool ret = server->Call(msg->params(), result);
                if (ret == false)
                {
                    LOG(LogLevel::ERROR) << "服务调用失败";
                    result[KEY_RESULT] = "服务调用失败";
                    return RpcResponse(conn, msg, result, RCode::RCODE_OTHER_ERROR);
                }
                // 4.返回结果
                return RpcResponse(conn, msg, result, RCode::RCODE_OK);
            }

            void Register(const ServerDescribe::ptr &server)
            {
                _server_manager->Insert(server);
            }

        private:
            void RpcResponse(const BaseConnection::ptr &conn, const RpcRequest::ptr &msg, const Json::Value &result, RCode rcode)
            {
                auto rsp = zgwrpc::MessageFactory::createMessage(zgwrpc::MType::RSP_RPC);
                zgwrpc::RpcResponse::ptr rsp_msg=std::dynamic_pointer_cast<zgwrpc::RpcResponse>(rsp);
                rsp_msg->setId(msg->rid());
                rsp_msg->setMType(zgwrpc::MType::RSP_RPC);
                rsp_msg->setResult(result);
                rsp_msg->setRCode(rcode);
                conn->send(rsp_msg);
            }

        private:
            ServerManager::ptr _server_manager;
        };

    }

}